<!--
 * @Author: Xujianchen
 * @Date: 2024-07-16 09:38:27
 * @LastEditors: xujianchen
 * @LastEditTime: 2024-07-16 09:45:57
 * @Description: 图片验证码
-->
<template>
  <canvas ref="canvasRef" width="120" height="40" class="cursor-pointer" @click="getImgCode" />
</template>

<script setup>
const modelValue = defineModel({ type: String, default: '' })

const canvasRef = ref(null)
const imgCode = ref('')

onMounted(() => getImgCode())

watch(
  () => modelValue.value,
  (newVal) => imgCode.value = newVal,
)

watch(imgCode, (newVal) => modelValue.value = newVal)

function getImgCode() {
  const el = canvasRef.value
  if (!el) return
  imgCode.value = draw(el, 120, 40)
}

function draw(el, width, height) {
  let imgCode = ''
  const NUMBER_STRING = '0123456789'
  const ctx = el.getContext('2d')
  if (!ctx) return imgCode

  ctx.fillStyle = randomColor(180, 230)
  ctx.fillRect(0, 0, width, height)
  for (let i = 0; i < 4; i += 1) {
    const text = NUMBER_STRING[randomNum(0, NUMBER_STRING.length)]
    imgCode += text
    const fontSize = randomNum(18, 41)
    const deg = randomNum(-30, 30)
    ctx.font = `${fontSize}px Simhei`
    ctx.textBaseline = 'top'
    ctx.fillStyle = randomColor(80, 150)
    ctx.save()
    ctx.translate(30 * i + 15, 15)
    ctx.rotate((deg * Math.PI) / 180)
    ctx.fillText(text, -15 + 5, -15)
    ctx.restore()
  }
  for (let i = 0; i < 5; i += 1) {
    ctx.beginPath()
    ctx.moveTo(randomNum(0, width), randomNum(0, height))
    ctx.lineTo(randomNum(0, width), randomNum(0, height))
    ctx.strokeStyle = randomColor(180, 230)
    ctx.closePath()
    ctx.stroke()
  }
  for (let i = 0; i < 41; i += 1) {
    ctx.beginPath()
    ctx.arc(randomNum(0, width), randomNum(0, height), 1, 0, 2 * Math.PI)
    ctx.closePath()
    ctx.fillStyle = randomColor(150, 200)
    ctx.fill()
  }
  return imgCode
}

function randomNum(min, max) {
  const num = Math.floor(Math.random() * (max - min) + min)
  return num
}

function randomColor(min, max) {
  const r = randomNum(min, max)
  const g = randomNum(min, max)
  const b = randomNum(min, max)
  return `rgb(${r},${g},${b})`
}

defineExpose({ getImgCode })
</script>